MODULE_NAME='DTV Music Client' 
(
    Dev dvIP_Connection,
    Dev dvDTV_Rcvr,
    Dev dvTPs[],
    Integer nPresetButtons[],
    Integer nPresetTextChans[],
    Char strFavsFileName[],
    Integer nMasterClient
)
(***********************************************************)
(***********************************************************)
(*  FILE_LAST_MODIFIED_ON: 04/04/2006  AT: 11:33:16        *)
(***********************************************************)
(* System Type : NetLinx                                   *)
(***********************************************************)
(* REV HISTORY:                                            *)
(***********************************************************)
(*
    $History: $
*)
//#DEFINE DEBUG
(***********************************************************)
(*          DEVICE NUMBER DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_DEVICE

(***********************************************************)
(*               CONSTANT DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_CONSTANT
cnMaxChannels = 1000;
cnMaxPanels = 30;
cnMaxFavs = 20;

cnMaxDebugLen = 200;

Long lUpdateTimeLineID = 1000;
Long lUpdateTimes[] = {8640000}; // 24 hours
//Long lUpdateTimes[] = {1800}; // 24 hours
nUpdateTimeQty = 1;

strIPAddress = 'www.paragonintranet.com'

Integer nDefaultFavs[]=
{
    243, // 1- Hair Guitar
    251, // 2- Classic Hits Blend
    248, // 3- Alternative
    247, // 4- Classic Rock
    231, // 5- Todays Hits
    233, // 6- Hottest Hits
    222, // 7- 80s
    223  // 8- 90s
    //266, // 9- Blues
    //263, // 10- Soft Hits
    //265, // 11- Smooth Jazz
    //225, // 12- Today Country
    //218, // 13- Holiday
    //234, // 14- Love Songs
    //256, // 15- Classic R+B
    //236, // 16- Metro Blend
    //273  // 17- Light Classical
    // 18- College Rock
    // 19- 
    // 20-
}           

(***********************************************************)
(*              DATA TYPE DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_TYPE

Structure _sDTVChans
{
    Float nChan
    Char  strChanName[35]
}
(***********************************************************)
(*               VARIABLE DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_VARIABLE
Volatile _sDTVChans sDTVChans[cnMaxChannels]
Volatile _sDTVChans sFavChans[cnMaxFavs]

Volatile Char strChannelFBBuffer[200]

Volatile Integer nCmd

Volatile SLong sIPResult;
Volatile Char strInputBuffer[15000];
Volatile Integer nIncomingVer;
Volatile Integer nCurrentVer;
Volatile Char strJunk[20];
Volatile Integer nTotalChanCount;

Volatile Float fCurrentChannel

(***********************************************************)
(*               LATCHING DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_LATCHING

(***********************************************************)
(*        SUBROUTINE/FUNCTION DEFINITIONS GO BELOW         *)
(***********************************************************)
(* EXAMPLE: DEFINE_FUNCTION <RETURN_TYPE> <NAME> (<PARAMETERS>) *)
(* EXAMPLE: DEFINE_CALL '<NAME>' (<PARAMETERS>) *)

Define_Call 'DEBUG_OUTPUT' (Integer nLine, Char strData[])
{
    #IF_DEFINED DEBUG
    Char strTempData[200];
    Integer nLen, nCurrentPos;
    
    nLen = Length_String(strData)
    If (nLen < cnMaxDebugLen)
    {
	Send_String 0,"__FILE__,' Line:',Itoa(nLine),' ',strData";
    }
    Else
    {
	strTempData = Left_String(strData,cnMaxDebugLen);
	Send_String 0,"__FILE__,' Line:',Itoa(nLine),' ',strTempData";
	nCurrentPos = cnMaxDebugLen
	While (nLen > nCurrentPos)
	{
	    strTempData = Mid_String(strData,nCurrentPos,cnMaxDebugLen);
	    nCurrentPos = nCurrentPos + cnMaxDebugLen
	    Send_String 0,"'Continued: ',strTempData";
	}
    }
    #END_IF
}

Define_Call 'SELECT_FAV' (Integer nPreset)
{
    Integer nTempSubChan
	
    //If (sFavChans[nPreset].nSubChan)
    //{
	//TODO
	//Call 'DEBUG_OUTPUT' (__Line__,"'Whoops there is no code in the sub chans section.'");
    //}
    //Else
    //{
	Call 'DEBUG_OUTPUT' (__Line__,"'Favs nPreset:',Itoa(nPreset),' Chan:',Itoa(sFavChans[nPreset].nChan)");
	Send_Command dvDTV_Rcvr,"'XCH',Itoa(sFavChans[nPreset].nChan)"
    //}
}

Define_Call 'SET_DEFAULT_FAVS'
{
    Stack_var Integer nI
    For (nI = 1; nI <= Length_String(nDefaultFavs); nI++)
    {
	sFavChans[nI].nChan = sDTVChans[nDefaultFavs[nI]].nChan 
	sFavChans[nI].strChanName = sDTVChans[nDefaultFavs[nI]].strChanName
    }
}

Define_Function CHAR[100] GET_IP_ERROR (LONG lERR)
{
  Switch (lERR)
  {
    Case 0:
      Return "";
    Case 2:
      Return "'IP ERROR (',ITOA(lERR),'): General Failure (IP_CLIENT_OPEN/IP_SERVER_OPEN)'";
    Case 4:
      Return "'IP ERROR (',ITOA(lERR),'): unknown host (IP_CLIENT_OPEN)'";
    Case 6:
      Return "'IP ERROR (',ITOA(lERR),'): connection refused (IP_CLIENT_OPEN)'";
    Case 7:
      Return "'IP ERROR (',ITOA(lERR),'): connection timed out (IP_CLIENT_OPEN)'";
    Case 8:
      Return "'IP ERROR (',ITOA(lERR),'): unknown connection error (IP_CLIENT_OPEN)'";
    Case 9:
      Return "'IP ERROR (',ITOA(lERR),'): Already closed (IP_CLIENT_CLOSE/IP_SERVER_CLOSE)'";
    Case 10:
      Return "'IP ERROR (',ITOA(lERR),'): Binding error (IP_SERVER_OPEN)'";
    Case 11:
      Return "'IP ERROR (',ITOA(lERR),'): Listening error (IP_SERVER_OPEN)'";
    Case 14:
      Return "'IP ERROR (',ITOA(lERR),'): local port already used (IP_CLIENT_OPEN/IP_SERVER_OPEN)'";
    Case 15:
      Return "'IP ERROR (',ITOA(lERR),'): UDP socket already listening (IP_SERVER_OPEN)'";
    Case 16:
      Return "'IP ERROR (',ITOA(lERR),'): too many open sockets (IP_CLIENT_OPEN/IP_SERVER_OPEN)'";
    Default:
      Return "'IP ERROR (',ITOA(lERR),'): Unknown'";
  }
}

(***********************************************************)
(*                STARTUP CODE GOES BELOW                  *)
(***********************************************************)
DEFINE_START
// Start the timeline to check for preset updates
Wait 500
{
    If (nMasterClient)
    {
	Timeline_Create(lUpdateTimeLineID, lUpdateTimes, nUpdateTimeQty, Timeline_Relative, Timeline_Repeat);
	sIPResult = IP_Client_Open(dvIP_Connection.Port, strIPAddress, 80, IP_TCP);
	Call 'DEBUG_OUTPUT' (__LINE__,"'IP_Client_Open:',Itoa(dvIP_Connection.Port)")
    }
}
(***********************************************************)
(*                THE EVENTS GO BELOW                      *)
(***********************************************************)
DEFINE_EVENT

Timeline_Event[lUpdateTimeLineID]
{
    If (nMasterClient)
    {
	sIPResult = IP_Client_Open(dvIP_Connection.Port, strIPAddress, 80, IP_TCP);
	Call 'DEBUG_OUTPUT' (__LINE__,"'IP_Client_Open:',Itoa(dvIP_Connection.Port)")
    }
}

Data_Event[dvDTV_Rcvr]
{
    String:
    {
	Stack_Var Integer nTPIndex, nI
	
	strChannelFBBuffer = Data.Text
	Call 'DEBUG_OUTPUT' (__Line__,"'strChannelFBBuffer:',strChannelFBBuffer");
	IF (Find_String(strChannelFBBuffer,'CHAN=',1))
	{
	    strJunk = Remove_String(strChannelFBBuffer,'CHAN=',1)
	    fCurrentChannel = Atof(strChannelFBBuffer)
	    Call 'DEBUG_OUTPUT' (__Line__,"'fCurrentChannel:',Itoa(fCurrentChannel)");
	}
	For (nI = 1; nI <= Max_Length_Array(sFavChans); nI++)
	{
	    If (fCurrentChannel == sFavChans[nI].nChan && sFavChans[nI].nChan != 0)
	    {
		Call 'DEBUG_OUTPUT' (__LINE__, "'Matched Channel:',Ftoa(fCurrentChannel)")
		On[dvTPs,nPresetButtons[nI]]
	    }
	    Else
	    {
		Off[dvTPs,nPresetButtons[nI]]
	    }
	}
    }
}

Channel_Event[dvDTV_Rcvr,255] // rebuild events
{
    Off:
    {
	Stack_Var Integer nI, nPos

	Rebuild_Event()
	Call 'DEBUG_OUTPUT' (__LINE__,"'Channel_Event[dvDTV,255] fCurrentChannel:',Ftoa(fCurrentChannel)")
	For (nI = 1; nI <= Length_Array(nPresetTextChans); nI++)
	{
	    Send_Command dvTPs,"'TEXT',Itoa(nPresetTextChans[nI]),'-',sFavChans[nI].strChanName"
	    Call 'DEBUG_OUTPUT' (__LINE__,"'TEXT',Itoa(nPresetTextChans[nI]),'-',sFavChans[nI].strChanName")
	    If (fCurrentChannel == sFavChans[nI].nChan && sFavChans[nI].nChan != 0)
	    {
		Call 'DEBUG_OUTPUT' (__LINE__, "'Matched Channel:',Ftoa(fCurrentChannel)")
		On[dvTPs,nPresetButtons[nI]]
	    }
	    Else
	    {
		Off[dvTPs,nPresetButtons[nI]]
	    }
	}
    }
}

Data_Event[dvIP_Connection]
{
    Online:
    {
	strInputBuffer="";
	If (nMasterClient)
	{
	    Send_String dvIP_Connection,"'GET /programming/presets/?q=dss HTTP/1.1',13,10,'Host:www.paragonintranet.com',13,10,13,10";
	    Call 'DEBUG_OUTPUT' (__Line__,"' GET /programming/presets/?q=dss HTTP/1.1 Host:www.paragonintranet.com'");
	}
    }
    String:
    {
	Call 'DEBUG_OUTPUT' (__Line__,"'Data.Text>',Data.Text,'<'");
	strInputBuffer = "strInputBuffer,Data.Text";
    }
    Offline:
    {
	Stack_Var Integer nI
	If (Remove_String(strInputBuffer,'version ',1) && Find_String(strInputBuffer,'EndOfFile',1))
	{
	    nIncomingVer = Atoi(strInputBuffer);
	    If (nIncomingVer > nCurrentVer)
	    {
		nCurrentVer = nIncomingVer;
		strJunk = Remove_String(strInputBuffer,"13",1);
		While(Find_String(strInputBuffer,"13",1))
		{
		    nI++;
		    sDTVChans[nI].strChanName = Remove_String(strInputBuffer,"13",1);
		    If (Find_String(sDTVChans[nI].strChanName,'EndOfFile',1))
		    {
			sDTVChans[nI].strChanName = '';
			nTotalChanCount = nI;
			Call 'SET_DEFAULT_FAVS'
			Break;
		    }
		    Else
		    {
			sDTVChans[nI].nChan = Atof(sDTVChans[nI].strChanName);
			strJunk = Remove_String(sDTVChans[nI].strChanName,'~',1);
			sDTVChans[nI].strChanName = Remove_String(sDTVChans[nI].strChanName,'~',1);
			sDTVChans[nI].strChanName = Left_String(sDTVChans[nI].strChanName,Length_String(sDTVChans[nI].strChanName)-1);  // remove the ~
			Call 'DEBUG_OUTPUT' (__Line__,"'Pos:',Itoa(nI),' Chan:',Ftoa(sDTVChans[nI].nChan),' Name:',sDTVChans[nI].strChanName");
		    }
		}
	    }
	}
    }
    OnError:
    {
	strInputBuffer=""
	If (nMasterClient)
	{
	    If (Data.Number != 14)
		sIPResult = 1  // set result to a invalid number (0 = connected <0 = error)
	    Call 'DEBUG_OUTPUT' (__LINE__, "GET_IP_ERROR(Data.Number)");
	}
    }
}

Button_Event[dvTPs,nPresetButtons]
{
    Push:
    {
	Call 'DEBUG_OUTPUT' (__LINE__, "'Entered PresetButton Event.'");
	Call 'SELECT_FAV' (Get_Last(nPresetButtons))
    }
}

Button_Event[dvTPs,228] // Chan Up
{
    Push:
    {
	On[dvDTV_Rcvr,22]
    }
    Release:
    {
	Off[dvDTV_Rcvr,22]
    }
}

Button_Event[dvTPs,229] // Chan Down
{
    Push:
    {
	On[dvDTV_Rcvr,23]
    }
    Release:
    {
	Off[dvDTV_Rcvr,23]
    }
}
(***********************************************************)
(*            THE ACTUAL PROGRAM GOES BELOW                *)
(***********************************************************)
DEFINE_PROGRAM

(***********************************************************)
(*                     END OF PROGRAM                      *)
(*        DO NOT PUT ANY CODE BELOW THIS COMMENT           *)
(***********************************************************)
